package com.mlink.ai.chat.ui.activity

import android.content.Intent
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import android.widget.PopupWindow
import androidx.core.content.res.ResourcesCompat
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.mlink.ai.chat.AiChatApplication
import com.mlink.ai.chat.assistant.robot.R
import com.mlink.ai.chat.assistant.robot.databinding.ActivityPromptCreateBinding
import com.mlink.ai.chat.assistant.robot.databinding.ItemCategoryPopupSelectorBinding
import com.mlink.ai.chat.bean.ExploreCategory
import com.mlink.ai.chat.bean.ExploreSubCategory
import com.mlink.ai.chat.constants.isCreateNewPrompt
import com.mlink.ai.chat.ui.fragment.PromptCreateEnsureAddDialogFragment
import com.mlink.ai.chat.ui.fragment.PromptCreateEnsureExitDialogFragment
import com.mlink.ai.chat.ui.viewmodel.ExploreViewModel
import com.mlink.ai.chat.utils.*

class PromptCreateActivity : BaseActivity<ActivityPromptCreateBinding>() {

    companion object {
        const val EXTRA_CATEGORY_ID = "category_id"
        const val KEY_LAST_SELECTED_CATEGORY_ID = "last_selected_category_id"
    }

    private var ensureDialogFragment: PromptCreateEnsureExitDialogFragment? = null

    private lateinit var categoryPopup: PopupWindow
    private var currentSelectedCategoryId = 0L
    private var preSelectedCategoryId = 0L

    private var categoryList = ArrayList<ExploreCategory>()

    private var currentCreatedCategoryName = ""

    private lateinit var adapter: CategoryAdapter

    private var isCategoryNameAdded = false

    private var isLaunchBilling = false

    private val viewModel: ExploreViewModel by lazy {
        ViewModelProvider(this)[ExploreViewModel::class.java]
    }


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        viewModel.getAllCategory(this)

        viewModel.categoriesLiveDada.observe(this) { it ->
            categoryList.clear()
            categoryList.addAll(it)

            currentSelectedCategoryId =
                intent.getLongExtra(EXTRA_CATEGORY_ID, categoryList[0].id)
            preSelectedCategoryId = currentSelectedCategoryId

            val category = it.find { it.id == currentSelectedCategoryId }
            binding.categorySpinnerTv.text = category?.categoryName ?: it[0].categoryName
        }

        AiChatApplication.app.appViewModel.getSubscribeLiveData().observe(this) {
            if (it && isLaunchBilling) {
                saveCategory()
            }
        }
    }

    override fun getViewBinding(): ActivityPromptCreateBinding {
        return ActivityPromptCreateBinding.inflate(layoutInflater)
    }

    override fun initViews() {
        binding.backIv.setOnClickListener {
            onBackPressed()
        }

        binding.categorySpinnerItem.setOnClickListener {
            if (this::categoryPopup.isInitialized) {
                if (categoryPopup.isShowing) {
                    categoryPopup.dismiss()
                } else {
                    categoryPopup.showAsDropDown(binding.categorySpinnerItem, 0, 5.dp2px())
                }
            } else {
                createCategorySelector(currentSelectedCategoryId)
                categoryPopup.showAsDropDown(binding.categorySpinnerItem, 0, 5.dp2px())
            }
        }

        binding.titleEdit.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
            }

            override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
            }

            override fun afterTextChanged(p0: Editable?) {
                if (binding.titleEdit.text.isNotEmpty()) {
                    binding.titleEdit.setBackgroundResource(R.drawable.shape_bg_prompt_create_text_normal)
                    binding.titleErrorTv.visibility = View.INVISIBLE
                }
            }

        })

        showPromptLimitText()
        binding.promptEdit.addTextChangedListener(object : TextWatcher {

            override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
            }

            override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
            }

            override fun afterTextChanged(p0: Editable?) {
                showPromptLimitText()

                if (binding.promptEdit.text.isNotEmpty()) {
                    binding.promptEdit.setBackgroundResource(R.drawable.shape_bg_prompt_create_text_normal)
                    binding.promptErrorTv.visibility = View.INVISIBLE
                }
            }

        })

        binding.doneBtn.setOnClickListener {
            AnalyticsEvents.AC_PPT_CREATE_CLICK.logEvent()
            if (binding.titleEdit.text.trim().isEmpty() || binding.promptEdit.text.trim()
                    .isEmpty()
            ) {
                if (binding.titleEdit.text.trim().isEmpty()) {
                    binding.titleEdit.setBackgroundResource(R.drawable.shape_bg_prompt_create_text_error)
                    binding.titleErrorTv.visibility = View.VISIBLE
                }

                if (binding.promptEdit.text.trim().isEmpty()) {
                    binding.promptEdit.setBackgroundResource(R.drawable.shape_bg_prompt_create_text_error)
                    binding.promptErrorTv.visibility = View.VISIBLE
                }
                return@setOnClickListener
            }

            val createCount = PromptUtils.getPromptCreateCount()
            if (!AiChatApplication.app.appViewModel.isSubscribed() && createCount >= 3) {
                startActivity(
                    Intent(this, BillingActivity::class.java)
                        .apply {
                            putExtra(BillingActivity.KEY_VIP_TYPE, AnalyticsParams.SUB_PROMPT)
                        })
                isLaunchBilling = true
            } else {
                saveCategory()
            }
        }

        binding.addIv.setOnClickListener {
            currentFocus?.clearFocus()
            doShowAddCategoryDialog()
        }

    }

    private fun saveCategory() {
        try {
            isCreateNewPrompt = true
            val list = PromptUtils.getCustomPromptCategoryList() as ArrayList

            val category = categoryList.find { it.id == currentSelectedCategoryId }
            category?.let {
                val subCategoryName = binding.titleEdit.text?.toString() ?: ""
                val subCategory = ExploreSubCategory(
                    PromptUtils.getSubCategoriesMaxId(category.subCategories) + 1,
                    subCategoryName,
                    binding.descriptionEdit.text?.toString() ?: "",
                    binding.promptEdit.text?.toString() ?: "",
                    true,
                    category.id,
                    categoryEventName = subCategoryName
                )
                var isHit = false
                list.forEach {
                    if (category.id == it.id) {
                        (it.subCategories as ArrayList).add(0, subCategory)
                        isHit = true
                    }
                }
                var createCount = PromptUtils.getPromptCreateCount()
                if (isHit) {
                    PromptUtils.saveCustomPromptList(list)
                    PromptUtils.savePromptCreateCount(++createCount)
                    PromptUtils.saveLastSelectedCategoryId(currentSelectedCategoryId)

                    logCreateSuccessEvent(category, subCategory)

                    finish()
                    return
                }
                category.apply {
                    isCustom =
                        id !in PromptUtils.getPresetCategoryIdList(this@PromptCreateActivity)
                    val subCategoryList = ArrayList<ExploreSubCategory>()
                    subCategoryList.add(subCategory)
                    subCategories = subCategoryList
                }
                list.add(0, category)
                PromptUtils.saveCustomPromptList(list)
                PromptUtils.savePromptCreateCount(++createCount)
                PromptUtils.saveLastSelectedCategoryId(currentSelectedCategoryId)

                logCreateSuccessEvent(category, category.subCategories[0])
            }
        } catch (e: java.lang.Exception) {

        }

        finish()
    }

    private fun logCreateSuccessEvent(
        category: ExploreCategory,
        subCategory: ExploreSubCategory
    ) {
        AnalyticsEvents.AC_PPT_CREATE_SUC.logEvent(Bundle().apply {
            putString(AnalyticsParams.CATEGORY, category.categoryEventName)
            val isCustom =
                currentSelectedCategoryId !in PromptUtils.getPresetCategoryIdList(this@PromptCreateActivity)
            val type = if (isCustom) "custom" else "preset"
            putString(AnalyticsParams.KEY_TYPE, type)
            val title = subStringSafely(subCategory.categoryEventName, 0, 100)
            putString(AnalyticsParams.KEY_TITLE, title)
            val desc = subStringSafely(subCategory.desc, 0, 100)
            putString(AnalyticsParams.DESCRIPTION, desc)
            val prompt = subStringSafely(subCategory.prompt, 0, 100)
            putString(AnalyticsParams.PROMPT, prompt)
        })
    }

    private fun showPromptLimitText() {
        binding.tvLimit.text = String.format(
            resources.getString(R.string.prompt_limit_500), binding.promptEdit.text.length
        )
    }

    override fun onBackPressed() {
        if (this::categoryPopup.isInitialized && categoryPopup.isShowing) {
            categoryPopup.dismiss()
            return
        }
        if (binding.titleEdit.text.trim().isNotEmpty() || binding.descriptionEdit.text.trim()
                .isNotEmpty()
            || binding.promptEdit.text.trim().isNotEmpty() || isSelectedCategoryChanged()
        ) {
            doShowEnsureExitDialog()
            return
        }
        super.onBackPressed()
    }

    private fun isSelectedCategoryChanged() =
        currentSelectedCategoryId != preSelectedCategoryId

    private fun doShowEnsureExitDialog() {
        ensureDialogFragment = PromptCreateEnsureExitDialogFragment()
        ensureDialogFragment?.show(supportFragmentManager, "")
        ensureDialogFragment?.listener =
            object : PromptCreateEnsureExitDialogFragment.OnDialogClickListener {
                override fun onDiscard() {
                    finish()
                }

                override fun onCancel() {
                    ensureDialogFragment?.dismissNow()
                }
            }
    }

    private fun doShowAddCategoryDialog() {
        val fragment = PromptCreateEnsureAddDialogFragment()
        fragment.setCreatedCategoryName(currentCreatedCategoryName)
        fragment.show(supportFragmentManager, "")
        fragment.listener =
            object : PromptCreateEnsureAddDialogFragment.OnDialogClickListener {
                override fun onDone(categoryName: String) {
                    if (categoryName.isNotEmpty()) {
                        currentCreatedCategoryName = categoryName
                    }

                    if (categoryName.isNotEmpty()) {
                        if (this@PromptCreateActivity::adapter.isInitialized) {
                            adapter.run {
                                val category: ExploreCategory
                                if (isCategoryNameAdded) {
                                    category = currentList[0]
                                    category.categoryName = categoryName
                                    categoryList[0].categoryName = categoryName
                                    categoryList[0].categoryEventName = categoryName
                                    currentSelectedCategoryId = category.id
                                    adapter.selectedId = category.id
                                } else {
                                    val id = PromptUtils.getCategoriesMaxId(
                                        currentList
                                    ) + 1
                                    category = ExploreCategory(id, categoryName).apply {
                                        categoryEventName = categoryName
                                    }
                                    currentSelectedCategoryId = id
                                    adapter.selectedId = id
                                    categoryList.add(0, category)
                                }
                                notifyDataSetChanged()
                            }

                        } else {
                            val id = PromptUtils.getCategoriesMaxId(
                                categoryList
                            ) + 1
                            val category = ExploreCategory(id, categoryName).apply {
                                categoryEventName = categoryName
                            }
                            currentSelectedCategoryId = id
                            categoryList.add(0, category)
                        }
                        isCategoryNameAdded = true
                        binding.categorySpinnerTv.text = categoryName
                    }
                    fragment.dismissNow()
                }

                override fun onCancel() {
                    fragment.dismissNow()
                }
            }
    }

    private fun createCategorySelector(selectedId: Long) {
        val contentView = layoutInflater.inflate(R.layout.popub_prompt_category_seletor, null)

        categoryPopup = PopupWindow(this).apply {
            width = binding.categorySpinnerItem.width
            height = WindowManager.LayoutParams.WRAP_CONTENT
            this.contentView = contentView
            isOutsideTouchable = true // 点击 PopupWindow 外区域，会关闭 PopupWindow
            setBackgroundDrawable(
                ResourcesCompat.getDrawable(
                    resources,
                    R.drawable.bg_main_example_item,
                    null
                )
            )
            elevation = 10f
            // 设置 PopupWindow 焦点，以便在 PopupWindow 显示时拦截 PopupWindow 外其他区域控件的点击事件
            isFocusable = true
        }

        val layoutManager = LinearLayoutManager(this)
        adapter = CategoryAdapter(selectedId)
        val recyclerView = contentView.findViewById<RecyclerView>(R.id.recycler_view)
        recyclerView.layoutManager = layoutManager
        recyclerView.adapter = adapter
        adapter.run {
            setOnItemClickedListener(object : CategoryAdapter.OnItemClickedListener {
                override fun onItemClicked(selectedId: Long, category: ExploreCategory) {
                    preSelectedCategoryId = currentSelectedCategoryId
                    currentSelectedCategoryId = selectedId
                    binding.categorySpinnerTv.text = category.categoryName
                    categoryPopup.dismiss()
                }

            })
            submitList(categoryList)
        }
    }

    class CategoryAdapter(var selectedId: Long) :
        ListAdapter<ExploreCategory, RecyclerView.ViewHolder>(
            MyDiffCallback()
        ) {

        private var onItemClickedListener: OnItemClickedListener? = null

        class MyDiffCallback : DiffUtil.ItemCallback<ExploreCategory>() {
            override fun areItemsTheSame(
                oldItem: ExploreCategory, newItem: ExploreCategory
            ): Boolean {
                return oldItem.id == newItem.id
            }

            override fun areContentsTheSame(
                oldItem: ExploreCategory, newItem: ExploreCategory
            ): Boolean {
                return oldItem == newItem
            }
        }

        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
            return ViewHolder(
                ItemCategoryPopupSelectorBinding.inflate(
                    LayoutInflater.from(parent.context),
                    parent,
                    false
                )
            )
        }

        override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
            val category = getItem(position)
            if (holder is ViewHolder) {
                holder.bind(position, category)
            }
        }

        inner class ViewHolder(val binding: ItemCategoryPopupSelectorBinding) :
            RecyclerView.ViewHolder(binding.root) {

            fun bind(position: Int, category: ExploreCategory) {

                binding.categoryNameTv.text = category.categoryName
                binding.root.apply {
                    if (selectedId == category.id) {
                        when (position) {
                            0 -> setBackgroundResource(R.drawable.item_category_list_selected_bg_top15radius)
                            itemCount - 1 -> setBackgroundResource(R.drawable.item_category_list_selected_bg_bottom15radius)
                            else -> setBackgroundResource(R.drawable.item_category_list_selected_bg_normal)
                        }
                    } else {
                        setBackgroundResource(R.color.transparent)
                    }
                    setOnClickListener {
                        selectedId = category.id
                        onItemClickedListener?.onItemClicked(selectedId, category)
                        notifyDataSetChanged()
                    }
                }
            }
        }

        fun setOnItemClickedListener(listener: OnItemClickedListener) {
            onItemClickedListener = listener
        }

        interface OnItemClickedListener {
            fun onItemClicked(selectedId: Long, category: ExploreCategory)
        }
    }
}